#ifndef _HTMLFORM_HPP_
#define _HTMLFORM_HPP_

#include "jhdefs.hpp"
#include "net/NameValueCollection.hpp"
#include <ostream>
#include <istream>
#include <string>
#include <vector>

NET_NAMESPACE_BEGIN

class CHTTPRequest;
class CPartHandler;
class CPartSource;

class CHTMLForm : public CNameValueCollection
{
public:
	CHTMLForm();
	explicit CHTMLForm(const std::string& encoding);
	CHTMLForm(const CHTTPRequest& request, std::istream& requestBody, CPartHandler& handler);
	CHTMLForm(const CHTTPRequest& request, std::istream& requestBody);
	explicit CHTMLForm(const CHTTPRequest& request);
	~CHTMLForm();

	void setEncoding(const std::string& encoding);
	const std::string& getEncoding() const;

	void addPart(const std::string& name, CPartSource* pSource);

	void load(const CHTTPRequest& request, std::istream& requestBody, CPartHandler& handler);
	void load(const CHTTPRequest& request, std::istream& requestBody);
	void load(const CHTTPRequest& request);

	void read(std::istream& istr, CPartHandler& handler);
	void read(std::istream& istr);
	void read(const std::string& queryString);

	void prepareSubmit(CHTTPRequest& request);

	std::streamsize calculateContentLength();

	void write(std::ostream& ostr, const std::string& boundary);
	void write(std::ostream& ostr);

	const std::string& boundary() const;

	int getFieldLimit() const;
	void setFieldLimit(int limit);

	static const std::string ENCODING_URL;       /// "application/x-www-form-urlencoded"
	static const std::string ENCODING_MULTIPART; /// "multipart/form-data"

	static const int         UNKNOWN_CONTENT_LENGTH;
protected:
	void readUrl(std::istream& istr);
	void readMultipart(std::istream& istr, CPartHandler& handler);
	void writeUrl(std::ostream& ostr);
	void writeMultipart(std::ostream& ostr);

private:
	CHTMLForm(const CHTMLForm&);
	CHTMLForm& operator = (const CHTMLForm&);

	enum Limits
	{
		DFL_FIELD_LIMIT = 100
	};

	struct Part
	{
		std::string name;
		CPartSource* pSource;
	};

	typedef std::vector<Part> PartVec;

	int         m_fieldLimit;
	std::string m_encoding;
	std::string m_boundary;
	PartVec     m_parts;
};


NET_NAMESPACE_END

#endif
